home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-05 / driverss.zip / IBMTOKEN.ASM < prev    next >
Assembly Source File  |  1991-03-25  |  80KB  |  2,062 lines

  1. ;*****************************************************************************;
  2. ;*                                                                           *;
  3. ;*     File:   IBMTOKEN.ASM                                                  *;
  4. ;*     Auth:   Brian Fisher                                                  *;
  5. ;*             Queens University                                             *;
  6. ;*             Computing and Communications Services                         *;
  7. ;*             Rm 2-50 Dupuis Hall                                           *;
  8. ;*             Kingston Ontario                                              *;
  9. ;*                                                                           *;
  10. ;*     Date:   September 3 1989                                              *;
  11. ;*                                                                           *;
  12. ;*     Purp:   Ethernet (3C501) packet driver for IBM Token Ring.  This      *;
  13. ;*             driver uses the IBM LAN support program DIR interface.        *;
  14. ;*             The current implementation supports IP and ARP.               *;
  15. ;*                                                                           *;
  16. ;*             (C) 1989 Queens University                                    *;
  17. ;*             Computing and Communications Services.  This portion of       *;
  18. ;*             the program remains the property of Queens University.        *;
  19. ;*                                                                           *;
  20. ;*===========================================================================*;
  21. ;*     Program Logic:                                                        *;
  22. ;*                                                                           *;
  23. ;*     IBMTOKEN extracts IP and ARP data from ethernet datagrams passed to   *;
  24. ;*     it by the ULP, makes any adjustments required, then builds a token    *;
  25. ;*     ring datagram and sends it out over the network.  The process is      *;
  26. ;*     reversed when packets are received.  IBMTOKEN supports token ring     *;
  27. ;*     source routing and functions in a bridged environment.                *;
  28. ;*                                                                           *;
  29. ;*     The ULP uses Ethernet 'Blue Book' encapsulation.  IBMTOKEN uses       *;
  30. ;*     802.2 LLC format for transmission on token ring.  The IBM (tm)        *;
  31. ;*     LAN Support Program is required.  IBMTOKEN uses the DIR interface     *;
  32. ;*     to send/receive packets on token ring.                                *;
  33. ;*                                                                           *;
  34. ;*     IP packets do not require any modifications, and are sent 'as is.'    *;
  35. ;*     ARP packets have an 'hwr' field that must be changed fro 1h to 6h     *;
  36. ;*     during send_pkt, and changed back to 1h from 6h during _receive.      *;
  37. ;*                                                                           *;
  38. ;*     The minimum size of an ethernet packet is 60 bytes (minus the 4 byte  *;
  39. ;*     ethernet checksum).  Token ring has no lower limit.  The ULP will     *;
  40. ;*     reject 'short' packets, so IBMTOKEN lies and tells it there are 60    *;
  41. ;*     bytes.                                                                *;
  42. ;*                                                                           *;
  43. ;*     ARP packets are 28 bytes in length.  The ULP rounds the size of a     *;
  44. ;*     packet up to 60 bytes, so there is extra data on the end of the ARP   *;
  45. ;*     packet.  IBMTOKEN trims this off, because token ring hosts reject     *;
  46. ;*     'too long' ARP packets.                                               *;
  47. ;*                                                                           *;
  48. ;*     The minimum size of an ethernet packet is 60 bytes.  The maximum      *;
  49. ;*     is 1514 bytes.  The buffer sizes for token ring send/receive are      *;
  50. ;*     set to accomodate this.                                               *;
  51. ;*                                                                           *;
  52. ;*     Source Routing:                                                       *;
  53. ;*                                                                           *;
  54. ;*     The ethernet entrenched logic of the ULP does not accomodate source   *;
  55. ;*     routing.  IBMTOKEN provides a mechanism for source routing that is    *;
  56. ;*     transparent to the ULP.  The RIF information associated with token    *;
  57. ;*     ring source addresses are placed in a cache.  When the ULP sends to   *;
  58. ;*     that address, the RIF information is extracted from the cache and     *;
  59. ;*     used to route the packet to the target host.                          *;
  60. ;*                                                                           *;
  61. ;*     RIF Cache Logic:                                                      *;
  62. ;*                                                                           *;
  63. ;*        The cache logic uses an LRU algorithm.  Each entry is time         *;
  64. ;*        stamped.  If all the slots in the cache are being used, the oldest *;
  65. ;*        entry (assumed to be the LRU) is replaced (bumped from the cache). *;
  66. ;*                                                                           *;
  67. ;*        If the ULP uses an address whose RIF has been bumped from the      *;
  68. ;*        cache, a mechanism exists to rediscover the source route.          *;
  69. ;*        IBMTOKEN attaches a phony RIF, with the broadcast bit set and      *;
  70. ;*        and empty route table.  This packet travels to all rings.  When    *;
  71. ;*        the foreign host responds, the RIF info is placed back in the      *;
  72. ;*        cache.  Subsequent transmissions will use the rediscovered RIF.    *;
  73. ;*                                                                           *;
  74. ;*        The size of the RIF cache should be set to handle the maximum      *;
  75. ;*        number of concurrent hosts.  This will minimize the bumping        *;
  76. ;*        effect and minimize all rings broadcasts.                          *;
  77. ;*                                                                           *;
  78. ;*        I chose this algorithm so the ULP would not require any special    *;
  79. ;*        coding to work.  It eliminates the need for special syncronization *;
  80. ;*        of the ARP and RIF cache's.                                        *;
  81. ;*                                                                           *;
  82. ;*===========================================================================*;
  83. ;*                                                                           *;
  84. ;*      Revs:  Sep 29 1989     Successful tests with TN3270, FTP, and FTPBIN.*;
  85. ;*             B. Fisher       Some fine tuning required.                    *;
  86. ;*                                                                           *;
  87. ;*             Oct 1  1989     Cleaning up code.  Found bug that prevented   *;
  88. ;*                             buffer1/buffer2..n copies from working.       *;
  89. ;*                                                                           *;
  90. ;*             Oct 15 1989     Rearranged buffer sizes to accomodate Adapt I *;
  91. ;*                                                                           *;
  92. ;*             Nov 15 1989     Added missing popf at end of recv_complt      *;
  93. ;*                             Fixed missing popf at end of recv_complt      *;
  94. ;*                                                                           *;
  95. ;*             Nov 19 1989     Added marker to show interrupt activity       *;
  96. ;*                             for debugging.                                *;
  97. ;*                                                                           *;
  98. ;*             Nov 20 1989     Add changes for Release 5 compatibility       *;
  99. ;*                                                                           *;
  100. ;*             Nov 21 1989     Fix es/bx reversal at get_size                *;
  101. ;*                                                                           *;
  102. ;*             Nov 22 1989     RIF not working because of confusion with     *;
  103. ;*                             SA bit acquired via ARP and SA bit acquired   *;
  104. ;*                             through Token Receive.  Send_Pkt now looks    *;
  105. ;*                             up all dest addresses in RIF table.           *;
  106. ;*                                                                           *;
  107. ;*             Nov 23 1989     Have DEBUG mode report RIF table address when *;
  108. ;*                             get_multicast_ call made.                     *;
  109. ;*                                                                           *;
  110. ;*             Nov 28 1989     Add phony RIF to 'local' addresses so the     *;
  111. ;*                             bridge will pass them on.  ARP acquired HW    *;
  112. ;*                             addresses need RIF to cross bridge.  This is  *;
  113. ;*                             done in send_pkt.                             *;
  114. ;*                                                                           *;
  115. ;*             Nov 29 1989     Fixed REPT macro in SA_blk so size of SA info *;
  116. ;*                             is correct.  Didn't hurt function, however.   *;
  117. ;*                                                                           *;
  118. ;*             Nov 29 1989     Clear broadcast bit in RIF before entry in    *;
  119. ;*                             table.  This prevents bridges from altering   *;
  120. ;*                             existing route.  FF,FF,FF,FF,FF,FF address    *;
  121. ;*                             uses broadcast bit so ARP will work.          *;
  122. ;*                                                                           *;
  123. ;*             Nov 29 1989     Predefined broadcast RIF entry direction bit  *;
  124. ;*                             polarity reversal prevented broadcast from    *;
  125. ;*                             going over the bridge.                        *;
  126. ;*                                                                           *;
  127. ;*             Version 1.A -   Production Version released at Queens         *;
  128. ;*                                                                           *;
  129. ;*             Jan 02 1990     Fix missing CLD in _receiver, shows up when   *;
  130. ;*                             TOKREUI is used instead of Lan Support Pgm... *;
  131. ;*                                                                           *;
  132. ;*             Version 1.B                                                   *;
  133. ;*             Jan 15 1990     Begin modifications for LRU algorithm in the  *;
  134. ;*             (alpha 0)       RIF cache.  3rd parm on cmd line sets number  *;
  135. ;*                             of entries in the cache, which is allocated   *;
  136. ;*                             using INT 21, Function 48h.  The cache        *;
  137. ;*                             routines are modified to handle the new addr  *;
  138. ;*                             mode for accessing the table.                 *;
  139. ;*                                                                           *;
  140. ;*             Jan 16 1990     Adding time mark info to SA_table structure.  *;
  141. ;*             (alpha 1)       add_entry initializes t_mark                  *;
  142. ;*                             loc_entry refreshes t_mark when match found   *;
  143. ;*                             add_entry uses LRU slot in table when slots   *;
  144. ;*                             are all in use.                               *;
  145. ;*                                                                           *;
  146. ;*             Jan 18 1990     Updated the program documentation to reflect  *;
  147. ;*                             the operation of the RIF cache.               *;
  148. ;*                                                                           *;
  149. ;*             Version 1.C     Add code for compatibility with Release 6 of  *;
  150. ;*             Mar 18 1990     Clarkson drivers, including TERMINATE call.   *;
  151. ;*                                                                           *;
  152. ;*             Version 1.D     Fix bug that prevents get_address from        *;
  153. ;*                             returning adapter 1's hardware address.       *;
  154. ;*                                                                           *;
  155. ;*****************************************************************************;
  156.  
  157. version        equ     14h                     ; Version D = 13h
  158.  
  159.        include defs.asm
  160.  
  161. debug          = 1                             ; set 1 for IRM marks on RX
  162.  
  163. alpha          = 1                             ; ALPHA Test Version = 1
  164. alpha_ver      = 1                             ; Which ALPHA Version...
  165.  
  166. hrs24          = 1573040                       ; ticks in 24 hour day
  167.  
  168. toke_vect      = 5Ch                           ; LAN Support Pgm Vector
  169. toke_wait      = 0FFh                          ; completion code wait status
  170. pool_size      = 512                           ; 8K space for buffer pool area
  171.  
  172. num_rcv_buff   = 2                             ; <2 defaults to 8
  173. recv_size      = 1536                          ; max size of card recieve buffer
  174. tran_size      = 1536                          ; max size of transmit buffer
  175.  
  176. STATION_ID     = 0;                            ; talk using direct station
  177.  
  178. RECV_OPTIONS   = 0C0h                          ; contiguous mac/data in bufs
  179.  
  180. open_cmd       =       3h                      ; LAN Support OpCodes
  181. interrupt_cmd  =       0h
  182. initialize_cmd =       20h
  183. close_cmd      =       4h
  184. modify_cmd     =       1h
  185. restore_cmd    =       2h
  186. trans_dir_cmd  =       0Ah
  187. free_ccb_cmd   =       27h
  188. recv_can_cmd   =       29h
  189. open_recv_cmd  =       28h
  190. get_status_cmd =       21h
  191.  
  192. SA_table_size  = 32                            ; default size of the RIF cache
  193. SA_min_size    = 2                             ; minimum size
  194. SA_max_size    = 1024                          ; maximum size
  195.  
  196. LLC_AC         = 10h                           ; access control LLC
  197. LLC_FC         = 40h                           ; frame control  LLC
  198. LLC_SSAP_DSAP  = 0AAAAh                        ; reversed for network <grin>
  199. LLC_CON        = 03h
  200.  
  201. MAC_hdr_size   = 22                            ; MAC+LLC+SNAP header length
  202.  
  203. not_SA_mask    = 7Fh
  204. SA_mask        = 80h
  205. RIF_size_mask  = 1Fh
  206. RIF_dir_bit    = 80h
  207.  
  208. broadcast_byte = 0FFh                          ; broadcast is FF,FF,FF,FF,FF,FF
  209.  
  210. ARP_type       = 0608h                         ; reversed for network order
  211. ARP_Eth_hwr    = 0100h                         ; reversed for network order
  212. ARP_Tok_hwr    = 0600h                         ; reversed for network order
  213. ARP_packet_size= 28                            ; fixes Ethernet assumption...
  214. phony_RIF      = 2082h                         ; used for bridges...
  215.  
  216.  
  217.  
  218. LLC_info_size  = 8                             ; LLC (3) + SNAP(5) = 8
  219.  
  220. mark           = 0F90h                         ; marker debug pos on screen 25
  221.  
  222. marker         macro   st,nd
  223.  
  224.                IF  debug NE 0                    ; do marker if debug <> 0
  225.  
  226.                pushf                             ; show 2 char marker on
  227.                push es                           ; 25th line, 1st column
  228.                push ax
  229.                mov  ax,0B800h
  230.                mov  es,ax
  231.                mov  al,'&st&'
  232.                mov  byte ptr es:[mark],al
  233.                mov  al,byte ptr es:[mark+1]      ; get color value
  234.                inc  al
  235.                and  al,0Fh
  236.                or   al,1
  237.                mov  byte ptr es:[mark+1],al      ; advance it to show activity
  238.                mov  al,'&nd'
  239.                mov  byte ptr es:[mark+2],al
  240.                mov  al,byte ptr es:[mark+3]
  241.                inc  al
  242.                and  al,0Fh
  243.                or   al,1
  244.                mov  byte ptr es:[mark+3],al
  245.                pop  ax
  246.                pop  es
  247.                popf
  248.  
  249.                ENDIF
  250.  
  251.                endm
  252.  
  253. call_token     macro   ccb
  254. ;--------------------------------------;
  255. ; loads address of CCB in ES:BX, then  ;
  256. ; calls the Token Ring Interface.      ;
  257. ;--------------------------------------;
  258.                mov     ax,cs
  259.                mov     es,ax
  260.                mov     bx,offset &ccb&
  261.                int     toke_vect
  262.                endm
  263.  
  264.  
  265. call_wait      macro
  266.                local   wait_loop
  267. ;---------------------------------------;
  268. ; assumes ES:BX points to a CCB.  Waits ;
  269. ; for a pending command to terminate.   ;
  270. ;---------------------------------------;
  271. wait_loop:
  272.                mov     al,es:[bx+2]
  273.                cmp     al,toke_wait
  274.                je      wait_loop
  275.                endm
  276.  
  277.  
  278. ticks          macro
  279. ;---------------------------------------;
  280. ; get system timer ticks in CX:DX       ;
  281. ;---------------------------------------;
  282.                mov     ah,0
  283.                int     1Ah
  284.                endm
  285.  
  286.  
  287. set_ptr        macro   dest,addr
  288. ;---------------------------------------;
  289. ; loads a far pointer with a near       ;
  290. ; address offset and CS:                ;
  291. ;---------------------------------------;
  292.                mov     ax,offset &addr&
  293.                mov     word ptr [&dest&],ax
  294.                mov     ax,cs
  295.                mov     word ptr [&dest&+2],ax
  296.                endm
  297.  
  298.  
  299. print$         macro   string
  300. ;---------------------------------------;
  301. ;  sends $ terminated string to screen  ;
  302. ;---------------------------------------;
  303.                mov     ah,9
  304.                mov     dx,offset &string&      ; print $ terminated string
  305.                int     21h
  306.                endm
  307.  
  308.  
  309. clr_struc      macro   name
  310. ;---------------------------------------;
  311. ;  clear all bytes of the named struc   ;
  312. ;  to zero.  Useful for Token calls.    ;
  313. ;---------------------------------------;
  314.                mov     cx,SIZE &name&          ; uses ax, es:di, cx
  315.                mov     ax,ds
  316.                mov     es,ax
  317.                mov     di,offset &name&
  318.                xor     al,al
  319.                cld
  320.                rep     stosb                   ; set all elements to 0
  321.                endm
  322.  
  323.  
  324. rdupb          macro   l,n
  325. &l&            db      ?
  326.                rept    &n&-1
  327.                db      ?
  328.                endm
  329.                endm
  330.  
  331.        IF debug NE 0
  332.  
  333. regs   struc                           ; from head.asm, [bp] references the
  334. _RES   dw      ?                       ; IRQ service parameters with these.
  335. _RDS   dw      ?
  336. _RBP   dw      ?
  337. _RDI   dw      ?
  338. _RSI   dw      ?
  339. _RDX   dw      ?
  340. _RCX   dw      ?
  341. _RBX   dw      ?
  342. _RAX   dw      ?
  343. _RIP   dw      ?
  344. _RCS   dw      ?
  345. _RCF   dw      ?               ;flags
  346. regs   ends
  347.  
  348.        ENDIF
  349.  
  350.  
  351. ccb_blk        struc                   ; CCB used for local token ring calls.
  352. adapter        db      ?               ; adapter 0 or 1
  353. command        db      ?               ; command code
  354. returncode       db      ?               ; command completion code
  355. work           db      ?               ; scratch
  356. pointer        dd      ?               ; queue pointer
  357. complt         dd      ?               ; command complete appendage
  358. parms          dd      ?               ; pointer to CCB parameter table
  359. ccb_blk ends
  360.  
  361.  
  362. init_parms     struc                   ; parameters for DIR_INITIALIZE
  363. bring_ups      dw      ?               ; result of bring up tests
  364. sram_addr      dw      ?               ; shared ram address
  365. reserved       dd      ?               ; not used...
  366. chk_exit       dd      ?               ; adapter check exit
  367. status         dd      ?               ; ring status exit
  368. error          dd      ?               ; PC error exit
  369. init_parms     ends
  370.  
  371.  
  372. o_parms        struc                   ; ccb parms for DIR_OPEN
  373. adapt          dd      ?               ; ptr to adapter parms
  374. direct         dd      ?               ; ptr to direct parms
  375. dlc            dd      ?               ; ptr to dlc parms
  376. msg            dd      ?               ; ptr to msg parms
  377. o_parms        ends
  378.  
  379.  
  380. ada_blk        struc                   ; adapter open parms table format
  381. err_code       dw      ?               ; open errors detected
  382. options        dw      ?               ; various options
  383. node_addr      dd      ?               ; node address ( 4 bytes here +  )
  384.                dw      ?               ; rest of node address ( 2 here  )
  385. group_add      dd      ?               ; group address
  386. func_add       dd      ?               ; functional address
  387. rcv_buff       dw      ?               ; number of receive buffers
  388. rcv_len        dw      ?               ; receive buffer length
  389. dhb_len        dw      ?               ; length of transmit buffers
  390. hold_buf       db      ?               ; number of tx buffers
  391.                db      ?               ; reserved
  392. lock_code      dw      ?               ; lock code
  393. id_addr        dd      ?               ; address of id code
  394. ada_blk        ends
  395.  
  396.  
  397. dir_blk        struc                   ; dir interfce open parms table format
  398. buf_size       dw      ?               ; size of direct station buffer
  399. pool_blks      dw      ?               ; number of 16 byte blocks in buff pool
  400. pool_addr      dd      ?               ; address of direct station buffer pool
  401. chk_exit       dd      ?               ; the rest can be 0 (defaults) for now
  402. stat_exit      dd      ?               ; ring status appendage pointer
  403. err_exit       dd      ?               ; PC error exit
  404. work_addr      dd      ?               ; work area segment value
  405. len_req        dw      ?               ; work area length requested
  406. len_act        dw      ?               ; actual length obtained
  407. dir_blk        ends
  408.  
  409.  
  410. dlc_blk        struc                   ; dlc interface open parms table format
  411. max_sap        db      ?               ; max number of saps
  412. max_sta        db      ?               ; max number of stations
  413. max_gsap       db      ?               ; max group saps
  414. max_gmem       db      ?               ; max members per group
  415. t1_tick1       db      ?               ; DLC timer t1 interval
  416. t2_tick1       db      ?               ; DLC timer t2 interval
  417. TI_tick1       db      ?               ; DLC timer TI interval
  418. t1_tick2       db      ?               ; DLC timer t1 group 2
  419. t2_tick2       db      ?               ; DLC timer t2 group 2
  420. TI_tick2       db      ?               ; DLC timer TI group 2
  421. dlc_blk        ends
  422.  
  423.  
  424. mod_blk        struc                   ; modify open parms parameter block
  425. buf_size       dw      ?               ; size of SAP buffers
  426. pool_blks      dw      ?               ; length in 16-byte, of buffer pool
  427. pool_adrs      dd      ?               ; address of direct interface buf pool
  428. chkt_exit      dd      ?               ; appendage, adapter check
  429. stat_exit      dd      ?               ; appendage, ring status
  430. err_exit       dd      ?               ; appendage, PC error exit
  431. new_opts       dw      ?               ; new options (wrap is ignored)
  432. mod_blk        ends
  433.  
  434.  
  435. tx_blk         struc                   ; transmit.dir.frame parameter block
  436. station        dw      ?               ; defines station sending data
  437. trans_fs       db      ?               ; * stripped FS field (returned)
  438. rsap           db      ?               ; RSAP (remote sap value)
  439. queue_1        dd      ?               ; address of TX queue 1
  440. queue_2        dd      ?               ; address of TX queue 2
  441. buf_len_1      dw      ?               ; length of buffer 1
  442. buf_len_2      dw      ?               ; length of buffer 2
  443. buffer_1       dd      ?               ; address of the first transmit buffer
  444. buffer_2       dd      ?               ; address of the second transmit buffer
  445. tx_blk         ends
  446.  
  447.  
  448. free_blk       struc                   ; buffer.free parameters
  449. st_id          dw      ?               ; station id
  450. buf_left       dw      ?               ; returns number of buffers left
  451. resrvd         dd      ?               ;
  452. first_buf      dd      ?               ; address of 1st buffer to free
  453. free_blk       ends
  454.  
  455.  
  456. get_blk        struc                   ; buffer.get parameters
  457. stn_id         dw      ?               ; station id
  458. buffr_lef      dw      ?               ; buffers left
  459. buff_get       db      ?               ; number of buffers to get
  460. resrv1         db      ?               ; 3 bytes not used
  461. resrv2         db      ?
  462. resrv3         db      ?
  463. frst_buff      dd      ?               ; address of buffer obtained
  464. get_blk        ends
  465.  
  466.  
  467. rx_blk         struc                   ; receive parms
  468. id             dw      ?               ; station id
  469. user_len       dw      ?               ; size of user space in buffer
  470. receiver       dd      ?               ; appendage for received data
  471. first_bf       dd      ?               ; pointer to 1st buffer
  472. opts           db      ?               ; receive options
  473. rx_blk         ends
  474.  
  475.  
  476. status_blk     struc                   ; parameter table for dir.status
  477. encoded_addr   dw      ?               ; adapters permanent ring address
  478.                dd      ?
  479. node_adrs      dw      ?               ; ring address set by open
  480.                dd      ?
  481. group_adrs     dd      ?
  482. func_adrs      dd      ?
  483.                REPT    16
  484.                db      ?
  485.                ENDM
  486.                REPT    3
  487.                dd      ?
  488.                ENDM
  489.                dw      ?
  490. status_blk     ends
  491.  
  492.  
  493.  
  494.  
  495.  
  496. mac_header     struc                   ; token ring mac header format
  497. AC             db      ?               ; access control byte
  498. FC             db      ?               ; frame control byte
  499.                rdupb   dest,EADDR_LEN
  500.                rdupb   source,EADDR_LEN
  501. dsap           db      ?               ; LLC dsap
  502. ssap           db      ?               ; LLC ssap
  503. control        db      ?               ; control byte
  504. ptype          db      ?
  505.                db      ?               ; SNAP header
  506.                db      ?
  507. ethtype        dw      ?               ; EtherType
  508. rif            dw      ?               ; optional RIF information
  509.                REPT    8               ; segment information
  510.                dw      ?               ; this is not its real position.
  511.                ENDM                    ; this is a variable length field...
  512. mac_header     ends
  513.  
  514.  
  515. SA_blk         struc
  516.                rdupb   s_addr,EADDR_LEN
  517. RCF            db      ?
  518.                db      ?
  519. route          dw      ?
  520.                REPT    7
  521.                dw      ?
  522.                ENDM    ?
  523. t_mark         dd      ?               ; LRU time marker...
  524. SA_blk         ends
  525.  
  526.  
  527. ether_hdr      struc                           ; ethernet header format
  528.                rdupb   ether_dest,EADDR_LEN
  529.                rdupb   ether_src,EADDR_LEN
  530. ether_type     dw      ?
  531. ether_hdr      ends
  532.  
  533.  
  534. first_buffer   struc                           ; Token receive 1st buffer
  535. next_buffer    dd      ?                       ; ptr to next buffer
  536. xx1            dw      ?
  537. data_size      dw      ?                       ; size of user data
  538.                REPT    12
  539.                db      ?
  540.                ENDM
  541. user_data      db      ?
  542. first_buffer   ends
  543.  
  544. user_data2     =       12                      ; 2nd buffer slightly different
  545.  
  546.  
  547.  
  548. ;=============================================================================;
  549. ;======================= START OF PROGRAM CODE ===============================;
  550. ;=============================================================================;
  551.  
  552. code           segment word public
  553.                assume  cs:code, ds:code
  554.  
  555. Token_address  db      EADDR_LEN dup (0)       ; holds my address after init.
  556.  
  557. ccb            ccb_blk <>                      ; scratch CCB
  558. free_ccb       ccb_blk <>
  559. tx_parms       tx_blk  <>                      ; transmit.dir.frame parms
  560. iparms         init_parms <>                   ; init parms
  561. pool_buff      db (pool_size+1)*16 dup (?)     ; buffer pool
  562. free_parms     free_blk <>                     ; buffer.free parameters
  563. get_parms      get_blk  <>                     ; buffer.get parameters
  564.  
  565. rx_ccb         ccb_blk <>                      ; receive CCB
  566. rx_parms       rx_blk  <>                      ; receive parms
  567.  
  568.  
  569. id_code        db 18 dup (0)   ; phony product id code
  570.                                ; (a real space saver...)
  571.  
  572. ada_parm       ada_blk <0,0,0,0,0,0,num_rcv_buff,recv_size,tran_size,1,0,0,0>
  573.  
  574. dir_parm       dir_blk <0,pool_size,0,0,0,0,0,0,0>
  575. dlc_parm       dlc_blk <0,0,0,0,0,0,0,0,0,0>
  576. init_parm      o_parms <0,0,0,0>
  577. initccb        ccb_blk <0,0,0,0,0,0,0>
  578. toke_status    status_blk <>
  579.  
  580. modparms mod_blk <0,pool_size,0,0,0,0,0>
  581. modccb ccb_blk < 0,modify_cmd,0,0,0,0,0>
  582.  
  583. lan_header  mac_header  <LLC_AC,LLC_FC>
  584.  
  585.  
  586. ;      SA RIF table has 1 entry in it by default, for the broadcast address.
  587. ;
  588. SA_index dw            1
  589. SA_size  dw            SA_table_size           ; size of table
  590.          dw            0                       ; parsed from cmd line
  591.  
  592. SA_delta dw            0                       ; delta t for LRU find
  593.          dw            0
  594. SA_ord   dw            0                       ; ordinal for LRU entry
  595.  
  596. memory_needed  dw      0                       ; scratch for memory calculation
  597.  
  598.  
  599. dir_interrupt  proc
  600. ;---------------------------------------;
  601. ; Entry: token_card (0 or 1)            ;
  602. ;  Exit: AX = CCB return code           ;
  603. ;---------------------------------------;
  604.                clr_struc ccb                   ; initialize CCB
  605.                mov     ax,token_card
  606.                mov     [ccb.adapter],al
  607.                mov     al,interrupt_cmd
  608.                mov     [ccb.command],al
  609.                call_token ccb                  ; call the interface
  610.                call_wait  ccb                  ; wait for completion
  611.                xor     ah,ah
  612.                mov     al,[ccb.returncode]        ; return the result in AX
  613.                ret
  614. dir_interrupt  endp
  615.  
  616.  
  617. dir_initialize proc
  618. ;---------------------------------------;
  619. ; Entry: token_card (0 or 1)            ;
  620. ;  Exit:                                ;
  621. ;       Ah = bring up return code       ;
  622. ;       Al = ccb return code            ;
  623. ;---------------------------------------;
  624.                clr_struc ccb                   ; clear ccb
  625.                clr_struc iparms                ; clear init parms (defaults)
  626.  
  627.                mov     ax,token_card           ; assign parameters
  628.                mov     [ccb.adapter],al
  629.                mov     al,initialize_cmd       ; command....
  630.                mov     [ccb.command],al
  631.  
  632.                set_ptr ccb.parms,iparms        ; link to init parms
  633.  
  634.                call_token ccb                  ; call the interface
  635.                call_wait  ccb                  ; wait for completion
  636.  
  637.                mov     ah,byte ptr iparms.bring_ups
  638.                mov  al,[ccb.returncode]
  639.  
  640.                ret
  641. dir_initialize endp
  642.  
  643.  
  644. dir_open_adapter proc
  645. ;---------------------------------------;
  646. ; Entry: token_card (0 or 1)            ;
  647. ;  Exit: AX = CCB return code           ;
  648. ;---------------------------------------;
  649.                mov     ax,token_card           ; get adapter number
  650.                mov     [initccb.adapter],al
  651.  
  652.                mov     al,open_cmd
  653.                mov     [initccb.command],al    ; 03h open_adapter command
  654.  
  655.                set_ptr ada_parm.id_addr,id_code
  656.                set_ptr dir_parm.pool_addr,pool_buff
  657.                set_ptr init_parm.adapt,ada_parm
  658.                set_ptr init_parm.direct,dir_parm
  659.                set_ptr init_parm.dlc,dlc_parm
  660.                set_ptr initccb.parms,init_parm
  661.  
  662.                xor     al,al
  663.                mov     [initccb.returncode],al
  664.  
  665.                call_token initccb              ; call the interface
  666.                call_wait  initccb              ; wait for completion
  667.  
  668.                xor  ah,ah
  669.                mov  al,[initccb.returncode]
  670.  
  671.                ret
  672. dir_open_adapter endp
  673.  
  674.  
  675. dir_close_adapter proc
  676. ;---------------------------------------;
  677. ; Entry: token_card (0 or 1)            ;
  678. ;  Exit: AX = CCB return code           ;
  679. ;---------------------------------------;
  680.                clr_struc ccb                   ; clear CCB
  681.  
  682.                mov     ax,token_card           ; initialize local CCB
  683.                mov     [ccb.adapter],al
  684.                mov     al,close_cmd            ; close command
  685.                mov     [ccb.command],al
  686.  
  687.                call_token ccb                  ; call the interface
  688.                call_wait  ccb                  ; wait for completion
  689.  
  690.                xor     ah,ah
  691.                mov     al,[ccb.returncode]        ; return the result
  692.                ret
  693. dir_close_adapter endp
  694.  
  695.  
  696. dir_modify_open proc
  697. ;---------------------------------------;
  698. ; Entry: token_card (0 or 1)            ;
  699. ;  Exit: AX = CCB return code           ;
  700. ;---------------------------------------;
  701.                mov     ax,token_card           ; get adapter number
  702.                mov     [modccb.adapter],al     ; command is a constant in ccb
  703.  
  704.                set_ptr modparms.pool_adrs,pool_buff
  705.                set_ptr modccb.parms,modparms
  706.  
  707.                xor     al,al
  708.                mov     [modccb.returncode],al
  709.  
  710.                call_token modccb       ; call the interface
  711.                call_wait  modccb       ; wait for completion
  712.  
  713.                xor     ah,ah
  714.                mov     al,[modccb.returncode]
  715.                ret
  716. dir_modify_open endp
  717.  
  718.  
  719. dir_restore_open proc
  720. ;---------------------------------------;
  721. ; Entry: token_card (0 or 1)            ;
  722. ;  Exit: AX = CCB return code           ;
  723. ;---------------------------------------;
  724.                clr_struc ccb                   ; initialize CCB
  725.  
  726.                mov     ax,token_card
  727.                mov     [ccb.adapter],al
  728.                mov     al,restore_cmd          ; dir.restore.open.parms
  729.                mov     [ccb.command],al
  730.  
  731.                call_token ccb                  ; call the interface
  732.                call_wait  ccb                  ; wait for completion
  733.  
  734.                xor     ah,ah
  735.                mov     al,[ccb.returncode]        ; return the result in AX
  736.                ret
  737. dir_restore_open endp
  738.  
  739.  
  740. transmit_dir_frame proc
  741. ;---------------------------------------;
  742. ; Entry: token_card (0 or 1)            ;
  743. ;                                       ;
  744. ; Stack:                                ;
  745. ;       sp+14  dw [usr seg]             ;
  746. ;       sp+12  dw [usr ofs]             ;
  747. ;       sp+10  dw [usrsize]             ;
  748. ;       sp+8   dw [hdr seg]             ;
  749. ;       sp+6   dw [hdr ofs]             ;
  750. ;       sp+4   dw [hdrsize]             ;
  751. ;       sp+2   dw [ret ofs]             ;
  752. ;       sp+0   dw [  bp   ]             ;
  753. ;                                       ;
  754. ;  Exit:                                ;
  755. ;       Ah = stripped FS field          ;
  756. ;       al = CCB return code            ;
  757. ;---------------------------------------;
  758.  
  759. trans_frame    struc                           ; transmit_dir_frame parms
  760. _x_bp          dw      ?                       ; old bp register
  761. _x_ret_ofs     dw      ?                       ; near return address
  762. header_size    dw      ?                       ; MAC header size
  763. llc_header     dd      ?                       ; address of header
  764. user_dsize     dw      ?                       ; user data size
  765. user_daddress  dd      ?                       ; user data address
  766. trans_frame    ends
  767.  
  768.                push    bp
  769.                mov     bp,sp
  770.  
  771.                mov     ax,cs
  772.                mov     ds,ax
  773.  
  774.                clr_struc ccb                   ; zero the CCB
  775.                clr_struc tx_parms              ; zero parameters
  776.  
  777.                mov     ax,token_card           ; initialize local CCB
  778.                mov     [ccb.adapter],al
  779.                mov     al,trans_dir_cmd        ; transmit.dir.frame
  780.                mov     [ccb.command],al
  781. ;
  782. ;      Set up transmit parameters, and link them to
  783. ;      the CCB...
  784. ;
  785.                mov     ax,offset tx_parms
  786.                mov     word ptr [ccb.parms],ax
  787.  
  788.                mov     ax,cs
  789.                mov     word ptr [ccb.parms+2],ax
  790. ;
  791.                mov     ax,STATION_ID
  792.  
  793.                mov     word ptr [tx_parms.station],ax
  794.  
  795.                mov     ax,[bp][user_dsize]
  796.                mov     word ptr [tx_parms.buf_len_2],ax
  797.  
  798.                mov     ax,word ptr [bp][user_daddress]
  799.                mov     word ptr [tx_parms.buffer_2],ax
  800.                mov     ax,word ptr [bp][user_daddress+2]
  801.                mov     word ptr [tx_parms.buffer_2+2],ax
  802.  
  803.                mov     ax,[bp][header_size]
  804.                mov     word ptr [tx_parms.buf_len_1],ax
  805.  
  806.                mov     ax,word ptr [bp][llc_header]
  807.                mov     word ptr [tx_parms.buffer_1],ax
  808.                mov     ax,word ptr [bp][llc_header+2]
  809.                mov     word ptr [tx_parms.buffer_1+2],ax
  810.  
  811.                call_token ccb                  ; call the interface
  812.                call_wait  ccb                  ; wait for completion
  813.  
  814.                mov     ah,[tx_parms.trans_fs]
  815.                mov     al,[ccb.returncode]
  816.  
  817.                pop     bp
  818.  
  819.                ret     (SIZE trans_frame)-4    ; (forget bp and ret address)
  820. transmit_dir_frame endp
  821.  
  822.  
  823. buffer_free    proc
  824. ;---------------------------------------;
  825. ; Entry:                                ;
  826. ;      sp+4    [ seg 1st buffer ]       ;
  827. ;      sp+2    [ ofs 1st buffer ]       ;
  828. ;      sp+0    [ bp             ]       ;
  829. ;                                       ;
  830. ;  Exit: AX = CCB return code           ;
  831. ;---------------------------------------;
  832.                mov     ax,cs
  833.                mov     ds,ax
  834.  
  835.                push    bp
  836.                mov     bp,sp
  837.  
  838.                clr_struc free_ccb
  839.                clr_struc free_parms
  840.  
  841.                mov     ax,token_card           ; initialize local CCB
  842.                mov     [free_ccb.adapter],al
  843.  
  844.                mov     al,free_ccb_cmd         ; buffer.free
  845.                mov     [free_ccb.command],al
  846.  
  847.                mov     ax,offset free_parms
  848.                mov     word ptr [free_ccb.parms],ax
  849.  
  850.                mov     ax,cs
  851.                mov     word ptr [free_ccb.parms+2],ax
  852. ;
  853. ;      Load free_parms to release buffer
  854. ;
  855.                mov     ax,STATION_ID
  856.                mov     word ptr [free_parms.st_id],ax
  857.  
  858.                mov     ax,word ptr [bp][4]
  859.                mov     word ptr [free_parms.first_buf],ax
  860.                mov     ax,word ptr [bp][6]
  861.                mov     word ptr [free_parms.first_buf+2],ax
  862.  
  863.                call_token free_ccb             ; call the interface
  864.  
  865.                xor     ah,ah
  866.                mov     al,[free_ccb.returncode]   ; return the result in AX
  867.  
  868.                pop     bp
  869.  
  870.                ret     4
  871. buffer_free    endp
  872.  
  873.  
  874. recv_cancel    proc
  875. ;---------------------------------------;
  876. ; Entry: token_card (0 or 1)            ;
  877. ;                                       ;
  878. ;  Exit:                                ;
  879. ;       AX = CCB return code            ;
  880. ;                                       ;
  881. ;---------------------------------------;
  882.                mov     ax,token_card           ; initialize local CCB
  883.                mov     [ccb.adapter],al
  884.  
  885.                mov     al,recv_can_cmd         ; receive.cancel
  886.                mov     [ccb.command],al
  887.  
  888.                xor     ax,ax                   ; word/bytes set to 0
  889.                mov     [ccb.returncode],al
  890.                mov     [ccb.work],al
  891.                mov     word ptr [ccb.pointer],ax
  892.                mov     word ptr [ccb.pointer+2],ax
  893.                mov     word ptr [ccb.complt],ax
  894.                mov     word ptr [ccb.complt+2],ax
  895.                mov     word ptr [ccb.parms+2],ax
  896.  
  897.                mov     ax,STATION_ID
  898.                mov     word ptr [ccb.parms],ax
  899.  
  900.                call_token ccb                  ; call the interface
  901.                call_wait  ccb                  ; wait for completion
  902.  
  903.                xor     ah,ah
  904.                mov     al,[ccb.returncode]        ; return the result in AX
  905.                ret
  906.  
  907. recv_cancel    endp
  908.  
  909.  
  910. open_receive proc
  911. ;---------------------------------------;
  912. ; Entry: token_card (0 or 1)            ;
  913. ;                                       ;
  914. ; Stack:                                ;
  915. ;       sp+6   dw [ret ofs]             ;
  916. ;       sp+4   dw [  bp   ]             ;
  917. ;       sp+2   dw [  ds   ]             ;
  918. ;       sp+0   dw [  es   ]             ;
  919. ;                                       ;
  920. ;  Exit:                                ;
  921. ;       AX = CCB return code            ;
  922. ;---------------------------------------;
  923.                mov     ax,cs
  924.                mov     ds,ax
  925.  
  926.                clr_struc rx_ccb
  927.                clr_struc rx_parms;
  928.  
  929.                mov     ax,token_card           ; initialize local CCB
  930.                mov     [rx_ccb.adapter],al
  931.  
  932.                mov     al,open_recv_cmd        ; receive
  933.                mov     [rx_ccb.command],al
  934.  
  935.                mov     ax,offset recv_complt
  936.                mov     word ptr [rx_ccb.complt],ax
  937.                mov     ax,cs
  938.                mov     word ptr [rx_ccb.complt+2],ax
  939. ;
  940. ;      Link receive parameters table
  941. ;
  942.                mov     ax,offset rx_parms
  943.                mov     word ptr [rx_ccb.parms],ax
  944.                mov     ax,cs
  945.                mov     word ptr [rx_ccb.parms+2],ax
  946.  
  947.                mov     ax,STATION_ID
  948.                mov     word ptr [rx_parms.id],ax
  949.  
  950.                mov     al,RECV_OPTIONS
  951.                mov     rx_parms.opts,al
  952.  
  953.                mov     ax,offset _receiver
  954.                mov     word ptr [rx_parms.receiver],ax
  955.                mov     ax,cs
  956.                mov     word ptr [rx_parms.receiver+2],ax
  957. ;
  958. ;       Note: The receive request is submitted, but it doesn't 'complete'
  959. ;             here.  So DON'T wait for a completion code!
  960. ;
  961.                call_token rx_ccb               ; call the interface
  962.  
  963.                xor     ah,ah
  964.                mov     al,[rx_ccb.returncode]     ; return the result
  965.                ret
  966. open_receive endp
  967.  
  968.  
  969. recv_complt proc
  970. ;
  971. ;      This procedure is an interrupt routine called by the Token Card
  972. ;      when receive completion occurs after an error.  All it should have
  973. ;      to do is resubmit the receive request, then exit.
  974. ;
  975.                pushf
  976.                push ax
  977.                push bx
  978.                push cx
  979.                push dx
  980.                push si
  981.                push di
  982.                push ds
  983.                push es
  984.                push bp
  985.                sti
  986.  
  987.                marker E,R
  988.                call open_receive               ; restart communications
  989.  
  990.                pop  bp
  991.                pop  es
  992.                pop  ds
  993.                pop  di
  994.                pop  si
  995.                pop  dx
  996.                pop  cx
  997.                pop  bx
  998.                pop  ax
  999.                popf
  1000.                iret
  1001. recv_complt    endp
  1002.  
  1003.  
  1004. recv_frame     struc                           ; stack frame for receiver
  1005.                RIF_size dw     ?               ; size of RIF in packet.
  1006.                user_buff dd    ?               ; pointer to users buffer
  1007.                user_size dw    ?               ; size of buffer needed/used
  1008.                _BP     dw      ?               ; register set on stack
  1009.                _ES     dw      ?
  1010.                _DS     dw      ?
  1011.                _DI     dw      ?
  1012.                _SI     dw      ?
  1013.                _DX     dw      ?
  1014.                _CX     dw      ?
  1015.                _BX     dw      ?
  1016.                _AX     dw      ?
  1017. recv_frame     ends
  1018.  
  1019.  
  1020. _receiver      proc
  1021. ;
  1022. ;      This interrupt procedure is called when the Token Ring
  1023. ;      card has data.
  1024. ;
  1025. ;      On entry, ds:si points to the CCB
  1026. ;                es:bx points to the receive first_buffer in the chain.
  1027. ;
  1028. ;
  1029.                 pushf                          ; save CPU environment
  1030.                 push   ax
  1031.                 push   bx
  1032.                 push   cx
  1033.                 push   dx
  1034.                 push   si
  1035.                 push   di
  1036.                 push   ds
  1037.                 push   es
  1038.                 push   bp
  1039.  
  1040.                 push   ax                      ; local variables: size of receive data
  1041.                 push   ax                      ; segment of user supplied buffer
  1042.                 push   ax                      ; offset of user supplied buffer
  1043.                 push   ax
  1044.  
  1045.                 mov    bp,sp                   ; set stack frame reference
  1046.  
  1047.                 sti                            ; enable further int activity
  1048.  
  1049.                 marker R,X
  1050. ;
  1051. ;      If the source address is mine, ignore the transmission!
  1052. ;
  1053.                mov     ax,cs
  1054.                mov     ds,ax
  1055.                mov     si,offset Token_address
  1056.                mov     di,bx
  1057.                add     di,user_data+source     ; ds:si -> token address
  1058.                                                ; es:di -> pkt
  1059.                mov     cx,EADDR_LEN
  1060.                push    word ptr es:[di]        ; save msb of address
  1061.  
  1062.                mov     al,es:[di]
  1063.                and     al,not_SA_mask          ; drop SA indicator
  1064.                mov     es:[di],al              ; fix the bit during compare
  1065. ;
  1066. ;      patch to fix direction bit problem...
  1067. ;
  1068.                cld
  1069.                repe    cmpsb                   ; do string compare now
  1070.                jne     not_mine
  1071.  
  1072.                mov     di,bx
  1073.                add     di,user_data+source
  1074.                pop     word ptr es:[di]        ; restore token address
  1075.  
  1076.                jmp     drop_buffer             ; from me, ignore it!
  1077.  
  1078. ;      es:bx -> 1st receive buffer
  1079. not_mine:
  1080.                mov     di,bx
  1081.                add     di,user_data+source
  1082.                pop     word ptr es:[di]        ; save MSB of source address
  1083.  
  1084.                xor     ax,ax
  1085.                mov     cx,ax
  1086.                mov     word ptr [bp][RIF_size],ax ; zero RIF size value
  1087.  
  1088. get_size:
  1089.                mov     ax,es
  1090.                or      ax,bx
  1091.                je      got_size
  1092.                add     cx,word ptr es:[bx][data_size]
  1093.                push    word ptr es:[bx][next_buffer]
  1094.                push    word ptr es:[bx][next_buffer+2]
  1095.                pop     es                      ; ************************
  1096.                pop     bx                      ; ************************
  1097.                jmp     get_size
  1098.  
  1099. got_size:
  1100.                sub     cx,LLC_info_size        ; adjust size for Token
  1101.  
  1102.                mov     ax,word ptr [bp][_ES]
  1103.                mov     es,ax
  1104.                mov     bx,word ptr [bp][_BX]   ; get buffer address
  1105.                mov     al,es:[bx][user_data+source]
  1106.                and     al,SA_mask              ; if SA, adjust total
  1107.                je      got_no_fix
  1108.  
  1109. ;
  1110. ;      How big is the RIF?
  1111. ;
  1112.                mov     ax,word ptr es:[bx][user_data+source+EADDR_LEN]
  1113.                and     ax,RIF_size_mask
  1114.                mov     word ptr [bp][RIF_size],ax
  1115. ;
  1116. ;      Take away size of RIF.  Upper level doesn't get it.
  1117. ;
  1118.                sub     cx,ax                   ; subtract RIF size
  1119.  
  1120. got_no_fix:
  1121. ;
  1122. ;      Min Ethersize is RUNT, so check it first, round up if necessary
  1123. ;
  1124.                cmp     cx,RUNT
  1125.                jge     no_adjust_cx
  1126.                mov     cx,RUNT
  1127.  
  1128. no_adjust_cx:
  1129.                mov     word ptr [bp][user_size],cx ; save size of receive data
  1130. ;
  1131. ;      Call recv_find to determine if the receiver wants the data,
  1132. ;      and where it should be stored.
  1133. ;
  1134.                mov     ax,word ptr [bp][_ES]   ; reload segment/offset
  1135.                mov     es,ax
  1136.                mov     di,word ptr [bp][_BX]   ; points to E-type in Token
  1137.                add     di,40                   ; assumes Buffer 1 format,
  1138.                add     di,word ptr [bp][RIF_size] ; RIF size added now...
  1139. ;
  1140. ;      if ARP type, convert hardware address space value back to Ethernet...
  1141. ;
  1142.                mov     ax,word ptr es:[di]     ;  -> EtherType in SNAP
  1143.                cmp     ax,ARP_type             ; ARP packet?
  1144.                jne     not_rx_arp
  1145.                mov     ax,ARP_Eth_hwr
  1146.                mov     word ptr es:[di][2],ax  ; fix 1st field of data
  1147.  
  1148. not_rx_arp:
  1149.                mov     dl,BLUEBOOK
  1150.                call    recv_find               ; es:di -> Snap E-Type, CX = data size
  1151.  
  1152.                mov     word ptr [bp][user_buff],di
  1153.                mov     ax,es
  1154.                mov     word ptr [bp][user_buff+2],ax
  1155.  
  1156.                or      ax,di
  1157.                jne     do_copy
  1158.                jmp     drop_buffer             ; if ptr is 0, doesn't want it!
  1159. ;
  1160. ;      Copy Token Ring data to users Ethernet format receive buffer.
  1161. ;
  1162. do_copy:
  1163. ;
  1164. ;      Since the upper level wants it, better keep the RIF info in case we
  1165. ;      want to send a return message.
  1166. ;
  1167.                mov     ax,word ptr [bp][_ES]
  1168.                mov     ds,ax
  1169.                mov     si,word ptr [bp][_BX]
  1170.                add     si,user_data+source     ; 1st byte of source address
  1171.                call    add_entry               ; do table maintenance
  1172. ;
  1173. ;      Copy data to the users buffer
  1174. ;
  1175.                mov     di,word ptr [bp][user_buff] ; Ethernet destination buffer
  1176.                mov     ax,word ptr [bp][user_buff+2]
  1177.                mov     es,ax
  1178.  
  1179.                mov     si,word ptr [bp][_BX]   ; Token Ring Source buffer
  1180.                mov     bx,si
  1181.                mov     ax,word ptr [bp][_ES]
  1182.                mov     ds,ax
  1183.                add     si,user_data            ; offset to user data
  1184. ;
  1185. ;      ds:si points to 1st token buffer
  1186. ;      es:di points to ethernet format buffer
  1187.  
  1188. ;      1. Copy Token/Ether  dest/source field to users buffer
  1189. ;         after stripping off the SA bit in the source address.
  1190.  
  1191.                mov    al,byte ptr ds:[si+source]    ;****************
  1192.                and    al,07Fh                       ;***** NEW ******
  1193.                mov    byte ptr ds:[si+source],al    ;****************
  1194.  
  1195.                mov    cx,EADDR_LEN*2           ; 2 address fields
  1196.                add    si,2                     ; offset to dest field
  1197.                cld
  1198.                rep     movsb
  1199.  
  1200.                add     si,LLC_info_size-2      ; assume no RIF,
  1201.                add     si,word ptr [bp][RIF_size] ; compensate for RIF
  1202.  
  1203.                movsw                           ; get ethertype
  1204.  
  1205.                mov     cx,[bx][data_size]      ; get length of data
  1206.                sub     cx,MAC_hdr_size         ; drop MAC header stuff
  1207.                sub     cx,[bp][RIF_size]       ; compensate for RIF
  1208.  
  1209. copy_buffer:
  1210.                cld
  1211.                rep     movsb                   ; copy rest of data to Ether..
  1212.                push    word ptr [bx][next_buffer]
  1213.                push    word ptr [bx][next_buffer+2]
  1214.                pop     ds
  1215.                pop     si
  1216.                mov     bx,si                   ; bx is base of buffer
  1217.                add     si,user_data2           ; si offsets to user data
  1218.                mov     cx,[bx][data_size]      ; length of user data
  1219.                mov     ax,ds
  1220.                or      ax,bx                   ; NULL pointer?
  1221.                jne     copy_buffer             ; no, keep copying...
  1222. ;
  1223. ;      Tell Upper layer I copied the data into his buffer...
  1224. ;
  1225.                mov     si,word ptr [bp][user_buff]
  1226.                mov     ax,word ptr [bp][user_buff+2]
  1227.                mov     ds,ax
  1228.                mov     cx,word ptr [bp][user_size]
  1229.  
  1230.                call    recv_copy
  1231. ;
  1232. ;      _ES:_BX points to 1st receive buffer, drop it, then exit
  1233. ;
  1234. drop_buffer:
  1235.                mov     ax,word ptr [bp][_ES]   ; tell Token, drop buffer
  1236.                mov     bx,word ptr [bp][_BX]
  1237.                push    ax
  1238.                push    bx
  1239.                call    buffer_free             ; seg:offs of 1st buff on stack
  1240.  
  1241.                pop     ax                      ; vacuum local variables off
  1242.                pop     ax                      ; the stack
  1243.                pop     ax
  1244.                pop     ax
  1245.  
  1246.                pop     bp
  1247.                pop     es
  1248.                pop     ds
  1249.                pop     di
  1250.                pop     si
  1251.                pop     dx
  1252.                pop     cx
  1253.                pop     bx
  1254.                pop     ax
  1255.                popf
  1256.  
  1257.                marker  r,x
  1258.  
  1259.                iret
  1260.  
  1261. _receiver      endp
  1262.  
  1263.  
  1264. comp_adr       proc
  1265. ;
  1266. ;      Compare two token address values, set flags without affecting any
  1267. ;      other registers.  JE or JNE to test result.
  1268. ;
  1269.                push    si
  1270.                push    di
  1271.                push    cx
  1272.                cld
  1273.                mov     cx,EADDR_LEN
  1274.                repe    cmpsb
  1275.                pop     cx
  1276.                pop     di
  1277.                pop     si
  1278.                ret
  1279. comp_adr       endp
  1280.  
  1281.  
  1282. make_adr       proc
  1283. ;
  1284. ;      Given CX as an ordinal (1..n) into the RIF_cache, build the address
  1285. ;      in ES:DI
  1286. ;
  1287.                push    ax
  1288.                push    cx
  1289.                dec     cx
  1290.                xor     di,di
  1291.                cmp     cx,0
  1292.                je      make_adr1
  1293. make_adr0:
  1294.                add     di,SIZE SA_blk          ; build index into SA_table
  1295.                loop    make_adr0
  1296.  
  1297. make_adr1:
  1298.                mov     ax,cs                   ; segment of table
  1299.                mov     es,ax
  1300.                add     di,offset RIF_cache     ; + offset to base of table
  1301.                pop     cx
  1302.                pop     ax
  1303.                ret
  1304. make_adr       endp
  1305.  
  1306.  
  1307.  
  1308. add_entry      proc
  1309. ;
  1310. ;      DS:SI -> Token Address, make an entry in the SA routing table
  1311. ;
  1312.                mov     cx,EADDR_LEN            ; don't add broadcasts to table
  1313.                push    si                      ; leave the default intact
  1314.                cld
  1315.  
  1316. add_entry0:
  1317.                lodsb                           ; Broadcast?
  1318.                cmp     al,broadcast_byte
  1319.                loope   add_entry0
  1320.                pop     si
  1321.                je      add_done                ; yes...
  1322.  
  1323.                mov     al,ds:[si]              ; is it a source route address?
  1324.                and     al,SA_mask
  1325.                je      add_done
  1326. ;
  1327. ;      Is it in the table?
  1328.  
  1329.                call    loc_entry
  1330.                jc      add_done                ; c = 1, its in the table.
  1331. ;
  1332. ;      if its not in the table, try to put it in a 'new' slot...
  1333. ;
  1334.                mov     cx,word ptr cs:[SA_index]
  1335.                cmp     cx,word ptr cs:[SA_size]
  1336.                jne     lotsa_room              ; room in table, make flat entry
  1337. ;
  1338. ;      If no new slots available, determine LRU entry and overwrite it...
  1339. ;
  1340.                push    ds                      ; save initial pointer
  1341.                push    si
  1342.                call    find_lru                ; returns cx ordinal into table
  1343.                pop     si                      ; restore initial pointer
  1344.                pop     ds
  1345.                jmp     do_entry
  1346. ;
  1347. ;      Update entry pointer, overwrite a new slot in the table...
  1348. ;
  1349. lotsa_room:    inc     cx
  1350.                mov     word ptr cs:[SA_index],cx ; advance the table index
  1351.  
  1352. ;      before entry is made, the broadcast bit must be cleared so bridges
  1353. ;      will leave the segment values alone.
  1354.  
  1355. do_entry:      mov     al,byte ptr ds:[si+EADDR_LEN]
  1356.                and     al,07Fh                 ; clear broadcast bit
  1357.                mov     byte ptr ds:[si+EADDR_LEN],al
  1358.  
  1359.                call    make_adr                ; build destination address
  1360.                push    si
  1361.                push    di
  1362.                push    es
  1363.                mov     cx,SIZE SA_blk
  1364.                cld
  1365.                rep     movsb                   ; copy RIF into table
  1366.                pop     es
  1367.                pop     di
  1368.                pop     si
  1369. ;
  1370. ;      Put time stamp on the new entry for LRU algorithm
  1371. ;
  1372.                ticks                           ; cx:dx = ticks count
  1373.                mov     word ptr es:[di+t_mark],dx
  1374.                mov     word ptr es:[di+t_mark+2],cx
  1375.  
  1376. add_done:
  1377.                ret
  1378. add_entry      endp
  1379.  
  1380.  
  1381. find_lru       proc
  1382. ;
  1383. ;      locates oldest entry in the RIF_cache, returns the ordinal number in
  1384. ;      CX.  The first entry is NEVER chosen because it contains the broadcast
  1385. ;      route predefined in the table!
  1386. ;
  1387. ;      CX = 2 .. cs:[SA_size]  ( range to be searched )
  1388. ;
  1389. ;      SA_delta  dword contains time difference for last one checked
  1390. ;      SA_ord    word  contains the ordinal of the least recently used
  1391. ;
  1392.        xor     ax,ax                           ; zero search variables
  1393.        mov     word ptr cs:[SA_delta],ax
  1394.        mov     word ptr cs:[SA_delta+2],ax
  1395.        mov     word ptr cs:[SA_ord],ax
  1396.  
  1397.        mov     cx,2                            ; 1st entry is NEVER touched!
  1398.  
  1399. find_loop:
  1400.        call    make_adr                        ; es:di -> current entry
  1401.        push    cx                              ; save index
  1402.        ticks                                   ; cx:dx = current ticks
  1403.        sub     cx,word ptr es:[di+t_mark+2]    ; ticks = mark
  1404.        sbb     dx,word ptr es:[di+t_mark]
  1405. ;
  1406. ;      if the result < 0, then ticks went past midnight.  Add 24 hrs in
  1407. ;      ticks to get the real delta t.
  1408. ;
  1409.        jge     _no_fix
  1410.        add     cx,((hrs24 shr 16) and 0ffffh)  ; longint to fix delta t
  1411.        adc     dx,(hrs24 and 0ffffh)           ; add 24 hours in ticks to
  1412.  
  1413. _no_fix:
  1414. ;
  1415. ;      If the result is greater than the stored SA_delta, replace it with
  1416. ;      this entry, then continue the loop...
  1417. ;
  1418.        push    cx                              ; save hi/low delta t result
  1419.        push    dx
  1420.        sub     cx,word ptr cs:[SA_delta+2]
  1421.        sbb     dx,word ptr cs:[SA_delta]
  1422.        jl      _no_replace
  1423.  
  1424. ;
  1425. ;      replace SA_ord and SA_delta with entry that has been around longer
  1426. ;
  1427.        pop     cs:[SA_delta]                   ; pull lo/hi delta t result
  1428.        pop     cs:[SA_delta+2]
  1429.        pop     cx                              ; get ordinal...
  1430.        mov     word ptr cs:[SA_ord],cx         ; replace SA_ord...
  1431.        jmp     _next_find
  1432.  
  1433. _no_replace:
  1434.        pop     cx
  1435.        pop     cx
  1436.        pop     cx
  1437.  
  1438. _next_find:
  1439.        inc     cx
  1440.        cmp     cx,word ptr cs:[SA_size]
  1441.        jle     find_loop
  1442.        jmp     _find_exit
  1443.  
  1444. _find_exit:
  1445.        mov     cx,SA_ord                       ; return ordinal of LRU
  1446.        ret
  1447.  
  1448. find_lru       endp
  1449.  
  1450.  
  1451.  
  1452. loc_entry      proc
  1453. ;
  1454. ;      DS:SI -> Token Address, locate entry in the SA routing table
  1455. ;      ES:DI -> SA information in table, if carry is set.
  1456. ;
  1457.                mov     cx,word ptr cs:[SA_index]  ; any entries in table?
  1458.                cmp     cx,0
  1459.                je      loc_done
  1460.  
  1461.  
  1462. loc_entry0:
  1463.                call    make_adr                ; build address into table
  1464.                call    comp_adr                ; compare Token Addresses
  1465.                je      loc_found               ; if matches, in table
  1466.                loop    loc_entry0
  1467.  
  1468. loc_done:
  1469.                clc
  1470.                ret
  1471.  
  1472. loc_found:                                     ; ES:DI points to matching entry
  1473.                ticks                           ; cx:dx = ticks value for
  1474.                mov     word ptr es:[di+t_mark],dx   ; refresh of existing
  1475.                mov     word ptr es:[di+t_mark+2],cx ; entry...
  1476.  
  1477.                stc
  1478.                ret
  1479.  
  1480. loc_entry endp
  1481.  
  1482.  
  1483. ;==============================================================================
  1484. ;
  1485. ;=================== DRIVER CODE  =============================================
  1486. ;
  1487. ;==============================================================================
  1488. ;
  1489. ;
  1490. ;      Token Ring Card number, parsed from command line
  1491. ;
  1492. token_card     dw      0                       ; default adapter number 0
  1493.                dw      0                       ; this prevents type error.
  1494.  
  1495. toke_ad_name   db      "Adapter (0 or 1) ",'$'
  1496. toke_sa_name   db      " RIF Cache Size: ",'$'
  1497.  
  1498. dir_open_mode  db      0                       ; set <> 0 if modify_open used
  1499. msg_initialize db      " INIT: Initializing the adapter...",CR,LF,'$'
  1500. msg_opening    db      "       Opening the adapter...",CR,LF,'$'
  1501. msg_complete   db      "       IBMTOKEN - Initialization complete.",CR,LF,'$'
  1502. msg_bad_adapter db     "ERROR: adapter must be 0 or 1.",CR,LF,'$'
  1503. no_mem_cache   db      "ERROR: RIF_cache value out of range!",CR,LF
  1504. msg_bad_init   db      "ERROR: Initialization Failed.",CR,LF
  1505.                db      "       Installation aborted!",CR,LF,'$'
  1506. msg_receiving  db      "       Starting receiver process...",CR,LF,'$'
  1507.  
  1508.        public  int_no
  1509. int_no db      0,0,0,0                 ;must be four bytes long for get_number.
  1510.  
  1511.        public  driver_class, driver_type, driver_name, driver_function, parameter_list
  1512. driver_class   db      BLUEBOOK,0      ;from the packet spec
  1513. driver_type    db      1               ;from the packet spec
  1514. driver_name    db      'IBMTokenR',0   ;name of the driver.
  1515. driver_function db      2
  1516.  
  1517. parameter_list  label   byte
  1518.         db      1       ;major rev of packet driver
  1519.         db      9       ;minor rev of packet driver
  1520.         db      14      ;length of parameter list
  1521.         db      EADDR_LEN       ;length of MAC-layer address
  1522.         dw      GIANT   ;MTU, including MAC headers
  1523.         dw      MAX_MULTICAST * EADDR_LEN       ;buffer size of multicast addrs
  1524.         dw      0       ;(# of back-to-back MTU rcvs) - 1
  1525.         dw      0       ;(# of successive xmits) - 1
  1526.         dw      0       ;Interrupt # to hook for post-EOI
  1527.                         ;processing, 0 == none,
  1528.  
  1529.        public  rcv_modes
  1530. rcv_modes      dw      4               ;number of receive modes in our table.
  1531.                dw      0,0,0,rcv_mode_3
  1532.  
  1533.  
  1534. sp_frame       struc
  1535. __bp           dw      ?
  1536. u_size         dw      ?
  1537. u_data         dd      ?
  1538. u_snap         dw      ?
  1539. sp_frame       ends
  1540.  
  1541.  
  1542.     public    as_send_pkt
  1543. ; The Asynchronous Transmit Packet routine.
  1544. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  1545. ;   interrupts possibly enabled.
  1546. ; Exit with nc if ok, or else cy if error, dh set to error number.
  1547. ;   es:di and interrupt enable flag preserved on exit.
  1548. as_send_pkt:
  1549.     ret
  1550.  
  1551.     public    drop_pkt
  1552. ; Drop a packet from the queue.
  1553. ; Enter with es:di -> iocb.
  1554. drop_pkt:
  1555.     assume    ds:nothing
  1556.     ret
  1557.  
  1558.     public    xmit
  1559. ; Process a transmit interrupt with the least possible latency to achieve
  1560. ;   back-to-back packet transmissions.
  1561. ; May only use ax and dx.
  1562. xmit:
  1563.     assume    ds:nothing
  1564.     ret
  1565.  
  1566.  
  1567.                public  send_pkt
  1568. send_pkt:
  1569. ;enter with ds:si -> packet, cx = packet length.
  1570. ;exit with nc if ok, or else cy if error, dh set to error number.
  1571.                assume  ds:nothing
  1572.                sti
  1573.                marker  T,X
  1574.  
  1575. ;
  1576. ;      construct local stack frame
  1577. ;
  1578.                mov     ax,word ptr ds:[si][ether_type]
  1579.                push    ax
  1580.                push    ds                      ; pointer to user data packet
  1581.                mov     ax,si
  1582.                add     ax,SIZE ether_hdr
  1583.                push    ax                      ; adjusted userdata pointer
  1584.                sub     cx,SIZE ether_hdr       ; adjust size for send
  1585.                push    cx
  1586.                push    bp
  1587.                mov     bp,sp                   ; use sp_frame for reference
  1588.  
  1589.  
  1590.                mov     ax,cs                   ; set dest pointer to LLC header
  1591.                mov     es,ax
  1592.  
  1593.                mov     di,offset lan_header.dest
  1594.                mov     cx,EADDR_LEN*2          ; copy dest|source fields
  1595.                cld
  1596.                rep  movsb
  1597. ;
  1598. ;      ds:si -> dest address, locate it in the SA RIF table
  1599. ;
  1600.                mov     ax,cs
  1601.                mov     ds,ax
  1602.                mov     si,offset lan_header.dest ; building LAN header info here
  1603.  
  1604. ; Set bit 7 of address, force lookup in table.  If it is found, add RIF,
  1605. ; otherwise, assume the local net.
  1606.  
  1607.                mov     al,byte ptr ds:[si]
  1608.                or      al,080h
  1609.                mov     byte ptr ds:[si],al
  1610.  
  1611.                call loc_entry
  1612.                jc   send_pkt1                  ; yes, copy out RIF information
  1613. ;
  1614. ;      add the rest of the fields to the LLC header, and set the size
  1615. ;      for the transmit call.
  1616. ;
  1617.                mov     al,byte ptr ds:[si]     ; dest address 1st byte,
  1618.                                                ; lop off SA bit
  1619.                and     al,not_SA_mask
  1620.                mov     byte ptr ds:[si],al
  1621.  
  1622.                mov     al,byte ptr ds:[si][EADDR_LEN]  ; force U bit high
  1623.                or      al,080h
  1624.                mov     byte ptr ds:[si][EADDR_LEN],al
  1625.  
  1626.                add     si,EADDR_LEN*2          ; point after dest/source addrs.
  1627.                mov     ax,es
  1628.                mov     bx,ds
  1629.                mov     ds,ax
  1630.                mov     es,bx
  1631.                xchg    si,di
  1632.  
  1633. ;      addresses acquired from ARP default to broadcast mode, using phony
  1634. ;      RIF info so the bridge will pass the packet along.
  1635. ;
  1636.                mov     ax,phony_RIF            ; copy phony RIF to LLC buffer,
  1637.                cld                             ; so 'local' can cross bridge..
  1638.                stosw
  1639.                jmp     send_pkt2
  1640.  
  1641. send_pkt1:
  1642. ;
  1643. ;      source/dest address need to be adjusted for routing.
  1644. ;
  1645.                mov     cx,EADDR_LEN
  1646.                push    si
  1647.  
  1648. send_pkt3:
  1649.                mov     al,byte ptr ds:[si]
  1650.                inc     si
  1651.                cmp     al,broadcast_byte
  1652.                loope   send_pkt3
  1653.                pop     si
  1654.                je      send_pkt4               ; broadcast address?
  1655.  
  1656.  
  1657.                mov     al,byte ptr ds:[si]     ; dest, lop off SA bit
  1658.                and     al,not_SA_mask
  1659.                mov     byte ptr ds:[si],al
  1660.  
  1661. send_pkt4:
  1662.                mov     al,byte ptr ds:[si][EADDR_LEN]
  1663.                or      al,SA_mask              ; set SA bit for RIF
  1664.                mov     byte ptr ds:[si][EADDR_LEN],al
  1665.  
  1666.                add     si,EADDR_LEN*2          ; ds:si -> dest for RIF info.
  1667.                add     di,EADDR_LEN            ; es:di -> RIF info, addr fld
  1668.  
  1669.                mov     bx,si                   ; keep RIF pos in LLC header
  1670.  
  1671.                mov     ax,word ptr es:[di]     ; get rif info
  1672.                and     ax,RIF_size_mask        ; get length of RIF
  1673.                mov     cx,ax
  1674.                mov     ax,es
  1675.                mov     dx,ds
  1676.                mov     ds,ax
  1677.                mov     es,dx
  1678.                xchg    si,di
  1679.                cld
  1680.                rep     movsb
  1681.  
  1682. ;
  1683. ;      Got RIF, fix direction bit.
  1684. ;
  1685.                mov     al,es:[bx][1]           ; RIF+1 = dir bit location
  1686.                xor     al,RIF_dir_bit          ; change direction
  1687.                mov     es:[bx][1],al
  1688.  
  1689. send_pkt2:
  1690. ;
  1691. ;      es:di -> target in LLC for the rest of the header,
  1692. ;      add LLC and SNAP information.
  1693. ;
  1694.                mov     ax,LLC_SSAP_DSAP        ; build LLC portion
  1695.                stosw
  1696.                mov     al,LLC_CON
  1697.                stosb
  1698.                xor     ax,ax                   ; 3 bytes for Ptype in SNAP
  1699.                stosw
  1700.                stosb
  1701.                mov     ax,word ptr [bp][u_snap]
  1702.                stosw
  1703. ;
  1704. ;      header is complete.
  1705. ;
  1706.                sub     di,offset lan_header    ; calculate size of LLC header
  1707. ;
  1708. ;      stack parameters for Transmit
  1709. ;
  1710.                pop     bp
  1711.  
  1712.                mov     ax,cs
  1713.                mov     ds,ax                   ; set ds for transmit entry
  1714.                push    ax
  1715.                mov     ax,offset lan_header
  1716.                push    ax
  1717.                push    di
  1718.  
  1719. ;--------------------------------------------------------------------
  1720. ;       If Users data is an ARP packet, 0806 type, then the 1st field
  1721. ;       must be changed from 0001 to 0006 for Token Ring broadcast, or
  1722. ;       no one will respond.  Funny, eh?  Another thing.  Since an ARP
  1723. ;       packet is smaller than the min size for Ethernet, the caller rounds
  1724. ;       up the size.  I have to change it back, or some Token hosts won't
  1725. ;       ARP for me.  The nerve!
  1726. ;
  1727.                push    bp
  1728.                mov     bp,sp
  1729.                mov     ax,word ptr [bp][14]    ; offset to ARP type on stack...
  1730.                pop     bp
  1731.  
  1732.                cmp     ax,ARP_type             ; network byte order is backwards
  1733.                jne     not_tx_arp
  1734. ;
  1735. ;      The first field of the ARP data has to be changed from 0001 to 0006
  1736. ;
  1737.                push    bp                      ; use trans_frame
  1738.                push    bp                      ; dummy entry on stack...
  1739.                mov     bp,sp
  1740.                mov     ax,word ptr [bp][user_daddress+2] ; addr of user data
  1741.                mov     es,ax
  1742.                mov     di,word ptr [bp][user_daddress]
  1743.  
  1744.                mov     ax,ARP_Tok_hwr
  1745.                mov     word ptr es:[di],ax     ; change ARP type to 0006
  1746.  
  1747.                mov     ax,ARP_packet_size      ; 28  bytes in an ARP packet
  1748.                mov     word ptr [bp][user_dsize],ax ; reset users data size
  1749.  
  1750.                pop     bp                      ; pop fake return address
  1751.                pop     bp                      ; pop real bp
  1752.  
  1753. not_tx_arp:
  1754.                call    transmit_dir_frame      ; send the packet
  1755.  
  1756.                pop     ax                      ; vacuum
  1757.                clc
  1758.                ret
  1759.  
  1760.  
  1761.                public  get_address
  1762. get_address:
  1763. ;get the address of the interface.
  1764. ;enter with es:di -> place to get the address, cx = size of address buffer.
  1765. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  1766.                assume  ds:code
  1767. ;
  1768.                push    di
  1769.                push    es
  1770.                push    cx
  1771.  
  1772.                mov     ax,cs
  1773.                mov     ds,ax
  1774.                clr_struc ccb
  1775.                clr_struc toke_status
  1776.  
  1777.                mov     ax,token_card           ; set adapter number
  1778.                mov     [ccb.adapter],al
  1779.                mov     al,get_status_cmd       ; get status returns address
  1780.                mov     ccb.command,al
  1781.                mov     ax,offset toke_status
  1782.                mov     word ptr [ccb.parms],ax
  1783.                mov     ax,ds
  1784.                mov     word ptr [ccb.parms+2],ax
  1785.  
  1786.                call_token ccb
  1787.                call_wait  ccb
  1788.  
  1789.                mov     si,offset toke_status.node_adrs
  1790.                pop     cx
  1791.                pop     es
  1792.                pop     di
  1793.                cmp     cx,EADDR_LEN            ; got the room for it?
  1794.                jb      get_address_fail
  1795.  
  1796.                cld
  1797.                mov     cx,EADDR_LEN
  1798.                rep     movsb
  1799.                mov     cx,EADDR_LEN
  1800.                clc
  1801.                ret
  1802.  
  1803. get_address_fail:
  1804.                stc
  1805.                ret
  1806.  
  1807.  
  1808.                public  set_address
  1809. set_address:
  1810. ;enter with ds:si -> Ethernet address, CX = length of address.
  1811. ;exit with nc if okay, or cy, dh=error if any errors.
  1812.                assume  ds:nothing
  1813.                clc
  1814.                ret
  1815.  
  1816.  
  1817. rcv_mode_3:
  1818. ;receive mode 3 is the only one we support, so we don't have to do anything.
  1819.        ret
  1820.  
  1821.  
  1822.        public  set_multicast_list
  1823. set_multicast_list:
  1824. ;enter with es:di ->list of multicast addresses, cx = number of bytes.
  1825. ;return nc if we set all of them, or cy,dh=error if we didn't.
  1826.        mov     dh,NO_MULTICAST
  1827.        stc
  1828.        ret
  1829.  
  1830.  
  1831.        public  get_multicast_list
  1832. get_multicast_list:
  1833. ;return with nc, es:di ->list of multicast addresses, cx = number of bytes.
  1834. ;return cy, NO_ERROR if we don't remember all of the addresses ourselves.
  1835. ;return cy, NO_MULTICAST if we don't implement multicast.
  1836.        mov     dh,NO_MULTICAST
  1837.        stc
  1838. ;
  1839. ;        DEBUG: get_multicast_list reports RIF accress instead, so I can
  1840. ;               check its contents from UL.
  1841. ;
  1842.        IF debug NE 0
  1843.  
  1844.        mov     ax,cs
  1845.        mov     _RES[bp],ax
  1846.        mov     ax,offset RIF_cache
  1847.        mov     _RDI[bp],ax
  1848.        mov     ax,word ptr cs:SA_index
  1849.        mov     _RCX[bp],ax
  1850.        clc
  1851.        ENDIF
  1852.        ret
  1853.  
  1854.  
  1855.                public  reset_interface
  1856. reset_interface:
  1857. ;reset the interface.
  1858.                assume  ds:code
  1859.                ret
  1860.  
  1861.  
  1862. ;called when we want to determine what to do with a received packet.
  1863. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  1864.                extrn   recv_find: near
  1865.  
  1866. ;called after we have copied the packet into the buffer.
  1867. ;enter with ds:si ->the packet, cx = length of the packet.
  1868.                extrn   recv_copy: near
  1869.  
  1870.                extrn   count_in_err: near
  1871.                extrn   count_out_err: near
  1872.  
  1873.                public  recv
  1874. recv:
  1875. ;called from the recv isr.  All registers have been saved, and ds=cs.
  1876. ;Upon exit, the interrupt will be acknowledged.
  1877.                assume  ds:code
  1878.                ret
  1879.  
  1880.         public  terminate
  1881. terminate:
  1882.         sti
  1883.         call    recv_cancel             ; shut down call-backs
  1884.         call    dir_close_adapter       ; close out the adapter
  1885.         ret
  1886.  
  1887.        public  recv_exiting
  1888. recv_exiting:
  1889. ;called from the recv isr after interrupts have been acknowledged.
  1890. ;Only ds and ax have been saved.
  1891.        assume  ds:nothing
  1892.        ret
  1893.  
  1894.  
  1895. ;=======================================================================;
  1896. ;============================== RIF Cache ==============================;
  1897. ;=======================================================================;
  1898. ;      The RIF_cache starts here.  Code appearing after the RIF cache   ;
  1899. ;      will be lost after initialization.  It becomes part of the RIF   ;
  1900. ;      cache area, or is released back to DOS.  The program code and    ;
  1901. ;      RIF_cache form a contiguous block in memory.  The first entry    ;
  1902. ;      in the cache is for the broadcast address.  This entry is NEVER  ;
  1903. ;      bumped from the cache!                                           ;
  1904. ;=======================================================================;
  1905.  
  1906. RIF_cache:
  1907.                SA_blk <0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,82h,0A0h,0>
  1908.  
  1909.  
  1910.  
  1911.                public  usage_msg
  1912. usage_msg      db      CR,LF
  1913.                db      "usage: IBMTOKEN <packet_int_no> <adapter> <RIF_cache>",CR,LF,LF
  1914.                db      "where: packet_int_no     is the interrupt vector",CR,LF
  1915.                db      "       adapter           is adapter 0 or 1",CR,LF
  1916.                db      "       RIF_cache         is number of hosts in RIF cache",CR,LF,CR,LF
  1917.                db      " note: IBM (tm) LAN Support Program required.",CR,LF,'$'
  1918.  
  1919.                public  copyright_msg
  1920. copyright_msg  db      CR,LF,"Token Ring Driver (3C501 emulation) Version "
  1921.                db      '0'+majver,".",'0'+version,CR,LF
  1922.                IF alpha NE 0
  1923.                db      "ALPHA TEST VERSION ",'0'+alpha_ver,CR,LF
  1924.                ENDIF
  1925.                db      "portions -",CR,LF
  1926.                db      "Copyright 1989, Queens University",CR,LF
  1927.                db      "Computing and Communications Services",CR,LF
  1928.                db      "Written by Brian Fisher",CR,LF
  1929.                IF  debug NE 0
  1930.                db      "*** DEBUG VERSION ***",CR,LF
  1931.                ENDIF
  1932.                db      LF,LF
  1933.                db      '$'
  1934.  
  1935.                extrn   set_recv_isr: near
  1936.  
  1937. ;enter with si -> argument string, di -> wword to store.
  1938. ;if there is no number, don't change the number.
  1939.                extrn   get_number: near
  1940.  
  1941.                public  parse_args
  1942. parse_args:
  1943. ;
  1944. ;      si points to next argument of command line...
  1945. ;
  1946.                mov     di,offset token_card    ; next argument is card number
  1947.                call    get_number
  1948.                jc      _parse_exit
  1949.                mov     di,offset SA_size       ; see if cache size ok...
  1950.                call    get_number
  1951. _parse_exit:   clc
  1952.                ret
  1953.  
  1954. et_error:                              ; token adapter number out of range
  1955. ;if we got an error,
  1956.                print$  msg_bad_adapter
  1957.                stc
  1958.                ret
  1959.  
  1960. sa_error:                              ; RIF cache allocation problem
  1961. ; if no memory for SA table,
  1962.                print$  no_mem_cache
  1963.                stc
  1964.                ret
  1965.  
  1966. et_init_error:
  1967.                call    dir_close_adapter       ; make sure adapter is closed
  1968.                print$  msg_bad_init
  1969.                stc
  1970.                ret
  1971.  
  1972.                public  etopen
  1973. ;
  1974. ;      Initialize the IBM Token Ring Adapter, determine memory requirements
  1975. ;      for the RIF_cache.
  1976. ;
  1977. etopen:
  1978.                mov     ax,cs
  1979.                mov     ds,ax
  1980.                assume cs:code, ds:code
  1981.  
  1982.                mov     ax,token_card           ; check card parm for range
  1983.                cmp     ax,1
  1984.                jg      et_error
  1985.                cmp     ax,0
  1986.                jl      et_error                ; less than zero?
  1987.  
  1988.                mov     ax,cs:[SA_size]         ; is the requested RIF cache
  1989.                cmp     ax,SA_min_size          ; size in range?
  1990.                jl      SA_error
  1991.                cmp     ax,SA_max_size
  1992.                jg      SA_error
  1993.  
  1994.                mov     bx,SIZE SA_blk          ; multiply to get bytes needed
  1995.                imul    bx
  1996.                add     ax,(offset RIF_cache)+15    ; offset + round up value
  1997.                adc     dx,0
  1998.                jne     SA_error                ; dx <> 0, way out of range!
  1999.  
  2000.                mov     cs:[memory_needed],ax   ; bytes needed for code+RIF
  2001.  
  2002. ;      Note: If a memory allocation error occurs when this init routine
  2003. ;      returns, the system will crash because the call backs are already
  2004. ;      defined for LAN Support.  I do a resize here, just to verify that
  2005. ;      it will work.
  2006. ;
  2007.                add     ax,15
  2008.                mov     cl,4
  2009.                shr     ax,cl
  2010.                mov     bx,ax
  2011.                mov     ax,cs                   ; get segment
  2012.                mov     es,ax
  2013.                mov     ah,4Ah                  ; resize memory block
  2014.                int     21h
  2015.                jc      SA_error                ; c=1, error doing memory
  2016.  
  2017. do_init:
  2018.                print$  msg_initialize          ; initialize the adapter
  2019.                call    dir_initialize
  2020.                cmp     ax,0
  2021.                jne     et_init_error
  2022.  
  2023.                print$  msg_opening             ; open the adapter
  2024.                call    dir_open_adapter
  2025.                cmp     ax,0
  2026.                jne     et_init_error
  2027.  
  2028. no_init:
  2029.                print$  msg_receiving           ; set up receive routines
  2030.                call    open_receive
  2031.                cmp     ax,0ffh
  2032.                jne     et_init_error           ; no receive open...
  2033.  
  2034.                print$  msg_complete            ; card ready to go
  2035.  
  2036.                mov     ax,cs
  2037.                mov     es,ax                   ; get Token Address for _receiver
  2038.                mov     di,offset Token_address
  2039.                mov     ds,ax
  2040.                mov     cx,6
  2041.                call    get_address
  2042.  
  2043. all_ok:
  2044. ;if all is okay, tell caller how much memory I want...
  2045.                mov     dx,cs:[memory_needed]
  2046.                clc
  2047.                ret
  2048.  
  2049.            public    print_parameters
  2050. print_parameters:
  2051.                ret
  2052.  
  2053. code           ends
  2054.                end
  2055.  
  2056. ;******************************************************************************
  2057. ;
  2058. ;*     End of file: IBMTOKEN.ASM                                              *
  2059. ;
  2060. ;******************************************************************************
  2061. ;
  2062.